package org.dftproject.genesis.data.genealogy.impl;

import java.text.DateFormatSymbols;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dftproject.genesis.data.genealogy.IInstant;
import org.dftproject.genesis.data.impl.EntityImpl;

public class InstantImpl extends EntityImpl implements IInstant {
	
	private static final Pattern pattern = Pattern.compile("(?:(ABT|CAL|EST)\\s+)?(?:(0?[1-9]|[1-2][0-9]|3[01]?)\\s+)?(?:(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\\s+)?([0-9]+)", Pattern.CASE_INSENSITIVE);
	private static final String[] months = new String[] { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
	
	private final String date;
	
	private boolean parsed;
	private boolean parseSucceeded;
	
	private Integer year;
	private Integer month;
	private Integer day;
	
	public InstantImpl(String date) {
		this.date = date;
	}
	
	protected void parse() {
		parsed = true;
		
		Matcher matcher = pattern.matcher(date);
		if (matcher.matches()) {
			year = Integer.valueOf(matcher.group(4));
			
			if (matcher.group(3) != null) {
				String monthValue = matcher.group(3);
				int monthIndex = 0;
				while (monthIndex < 12 && !monthValue.equalsIgnoreCase(months[monthIndex++]));
				if (monthIndex <= 12)
					month = monthIndex;
			}
			
			if (matcher.group(2) != null)
				day = Integer.valueOf(matcher.group(2));
			
			/*if (matcher.group(1) != null) {
				if ("ABT".equals(matcher.group(1)))
					addAttribute(new AttributeImpl(GenealogyConstants.note, new RawNote("Approximate")));
				else if ("CAL".equals(matcher.group(1)))
					addAttribute(new AttributeImpl(GenealogyConstants.note, new RawNote("Calculated")));
				else if ("EST".equals(matcher.group(1)))
					addAttribute(new AttributeImpl(GenealogyConstants.note, new RawNote("Estimated")));
			}*/
			
			parseSucceeded = true;
		}
	}
	
	public Long getMillis() {
		if (!parsed)
			parse();
		if (!parseSucceeded)
			return null;
		return new GregorianCalendar(year, month == null ? 5 : month - 1, day == null ? 15 : day).getTimeInMillis();
	}

	public String toString(Locale locale) {
		if (!parsed)
			parse();
		if (!parseSucceeded)
			return date;
		
		StringBuilder sb = new StringBuilder();
		
		if (month != null) {
			sb.append(new DateFormatSymbols().getMonths()[month - 1]);
			if (day != null || year != null)
				sb.append(" ");
		}
		if (day != null) {
			sb.append(day);
			if (year != null)
				sb.append(", ");
		}
		if (year != null) {
			sb.append(year);
		}
		
		return sb.toString();
	}
	
	@Override
	public String toString() {
		return toString(Locale.getDefault());
	}

	public final Integer getYear() {
		return year;
	}

	public final Integer getMonth() {
		return month;
	}

	public final Integer getDay() {
		return day;
	}
}
